#ifndef DRV_DJI_H
#define DRV_DJI_H

#include "can.h"

#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"

/**
 * @brief 大疆电机实例
 */
typedef struct
{
    /* 电调参数 */
    uint8_t motorID;      // 电调ID
    uint8_t motorIDGroup; // 电调ID所在的组

    /* CAN通信相关 */
    CAN_HandleTypeDef *hcan; // CAN控制器的句柄
    uint32_t cmdStdID;       // 发送控制指令到CAN控制器的标识符
    uint8_t cmdBufRow;       // 控制指令缓冲区中, 电机实例对应的行号
    uint8_t cmdBufColHigh;   // 控制指令缓冲区中, 电机实例对应的指令高8位的列号
    uint8_t cmdBufColLow;    // 控制指令缓冲区中, 电机实例对应的指令低8位的列号

    /* 角度信息相关 */
    FunctionalState initFlag; // 初始化标志
    uint8_t initCnt;          // 用于初始化的计数器
    uint16_t lastAngle;       // 上次的机械角度
    int16_t overflowCnt;      // 机械角度溢出次数
} Dji_t;

/**
 * @brief 大疆电机初始化结构体
 */
typedef struct
{
    /* 电调参数 */
    uint8_t motorID; // 电调ID

    /* CAN通信相关 */
    CAN_HandleTypeDef *hcan; // CAN控制器的句柄
} DjiInit_t;

/**
 * @brief 大疆电机反馈信息的消息结构体
 */
typedef struct
{
    uint16_t angle;      // 机械角度
    int16_t speed;       // 转速, 单位为rpm
    int16_t torque;      // 实际转矩
    int16_t overflowCnt; // 溢出次数
} DjiMsg_t;

/**
 * @brief 初始化一个大疆电机实例
 * @param motor: 大疆电机实例
 * @param motorInit: 大疆电机初始化结构体
 * @retval None
 */
void DJI_Init(Dji_t *motor, DjiInit_t *motorInit);

/**
 * @brief 处理大疆电机实例的电流指令
 * @param motor: 大疆电机实例
 * @param iq: 电流值
 * @param mutex: 互斥锁
 * @retval None
 */
void DJI_WriteCmdBuf(Dji_t *motor, int16_t iq, SemaphoreHandle_t mutex);

/**
 * @brief 此函数放置在ISR中, 更新大疆电机实例的反馈信息
 * @param rxData: CAN接收的缓存数组
 * @param motor: 大疆电机实例
 * @param motorInfoBoxHandle: 存放电机反馈信息的邮箱句柄
 * @retval None
 */
void ISR_DJI_UpdateInfo(uint8_t rxData[], Dji_t *motor, QueueHandle_t motorInfoBoxHandle);

/**
 * @brief 获取2006电机输出端转速, 单位为rpm
 */
float DJI_GetM2006Rpm(QueueHandle_t motorInfoBoxHandle);

/**
 * @brief 获取3508电机输出端转速, 单位为rpm
 */
float DJI_GetM3508Rpm(QueueHandle_t motorInfoBoxHandle);

/**
 * @brief 获取大疆电机的编码器计数
 */
int32_t DJI_GetCnt(QueueHandle_t motorInfoBoxHandle);

/**
 * @brief 获取2006电机输出端位置, 单位为r
 */
float DJI_GetM2006Pos(QueueHandle_t motorInfoBoxHandle, int32_t baseCnt);

/**
 * @brief 获取3508电机输出端位置, 单位为r
 */
float DJI_GetM3508Pos(QueueHandle_t motorInfoBoxHandle, int32_t baseCnt);

#endif //DRV_DJI_H
